package com.imooc.ecommerce.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.imooc.ecommerce.block_handler.CustomBlockHandler;
import com.imooc.ecommerce.vo.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 流控规则硬编码 Controller
 *
 * @author zhangshao
 * @since 2023/12/6 19:28
 */
@Slf4j
@RestController
@RequestMapping("/code")
public class FlowRuleCodeController {

    /**
     * 初始化流控规则
     */
    @PostConstruct
    public void init() {
        //流控规则集合
        List<FlowRule> flowRuleList = Lists.newArrayList();
        //创建流控规则
        FlowRule flowRule = new FlowRule();
        // 设置流控规则qps,限流阈值类型(QPS,并发线程数)
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 流量控制手段
        flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        // 设置受保护的资源
        flowRule.setResource("flowRuleCode");
        // 设置受保护的资源的限流
        flowRule.setCount(1);
        flowRuleList.add(flowRule);

        //加载配置好的规则
        FlowRuleManager.loadRules(flowRuleList);
    }

    /**
     * 采用硬编码限流规则的 Controller方法
     *
     * @return
     */
    @GetMapping("/flow-rule")
    // @SentinelResource(value = "flowRuleCode")
//    @SentinelResource(value = "flowRuleCode",blockHandler = "handleException")
    @SentinelResource(value = "flowRuleCode", blockHandler = "commonHandlerBlockException", blockHandlerClass = CustomBlockHandler.class)
    public CommonResponse<String> flowRuleCode() {
        log.info("request flowRuleCode");
        return new CommonResponse<>(0, "", "imooc-qinyi-ecommerce");
    }

    /**
     * 当限流异常抛出时,指定调用的方法
     * 是一个兜底策略
     *
     * @param ex BlockException
     * @return
     */
    public CommonResponse<String> handleException(BlockException ex) {
        log.error("has block exception:[{}]", JSON.toJSONString(ex.getRule()));
        return new CommonResponse<>(-1, "flow rule exception", ex.getClass().getCanonicalName());
    }
}
